<?php
require_once 'drivers/interface.php';


/**
 * Класс кэширования
 * 
 * @package Progmatic
 * @author Ladygin Sergey
 * @copyright 2009 Ladygin Sergey
 */
Class Cache {
    
    /**
     * Объект-драйвер
     * @var odject
     */
    private static $Driver;
    
    /**
     * Время жизни кэша
     * @var int
     */
    private static $LifeTime = 0;
    
    /**
     * Флаг режима отладки
     * Если true включен, false выключен
     * @var boolean
     */
    private static $DebugMode = false;
    
    /**
     * Флаг включен кэш или нет
     * Если true включен, false выключен
     * @var boolwan
     */
    private static $Enable = true;
    
    /**
     * Конструктор
     * @param string $driver Название драйвера
     * @param int $LifeTime Время жизни по умолчанию
     * @param mixed $params Параметры которые передаются драйверу
     * @return void
     */
    public function __construct($driver = 'File', $LifeTime = 0, $params = NULL) {
        
        if (!empty(self::$Driver)) {
            
            return $this;
        }
        
        $file = 'drivers/'.$driver.'Driver.php';
        $class = $driver.'Driver';
        
        try {
        
            require_once $file;
        }
        catch(Exception $e) {
            
            throw new CacheException('Driver files do not exist!');
        }
        
        if(!class_exists($class)) {
            
            throw new CacheException('Class driver does not exist');
        }
        
        self::$Driver = new $class($params);
        self::$LifeTime = $LifeTime;
        
        if (!self::$Driver instanceof CacheInterface) {
            
            throw new CacheException('Class driver incorrect');
        }
    }
    
    
    /**
     * Сохранение данных в кэш
     * @param string $group Группа
     * @param string $identifier Индентификатор
     * @param mixed $data Данный для сохранения
     * @return boolean
     */
    public static function set($group, $identifier, $data) {
        
        if (!self::$Enable) {
            
            return false;
        }
        
        try {
            
            if(self::$Driver->exists($group, $identifier)) return true;
            
            $data = (is_array($data)) ? serialize($data) : $data;
            return self::$Driver->set($group, $identifier, $data);
        }
        catch (CacheException $e){
            
            if(self::$DebugMode) throw $e;
            else return false;
        }
    }
    
    
    /**
     * Получение данных из кэша
     * @param string $group Группа
     * @param string $identifier Индентификатор
     * @param boolean $unpack Распаковывать массив или нет
     * @param int $lifeTime Время жизни данного кэша
     * @return mixed
     */
    public static function get($group, $identifier, $unpack = false, $lifeTime = 0) {
        
        if (!self::$Enable) {
            
            return false;
        }
        
        try {
            
            if (!is_numeric($lifeTime) && $lifeTime == self::$LifeTime) {
                
                $lifeTime =  self::$LifeTime;
            }
            
            if(!self::$Driver->exists($group, $identifier)) return false;
            
            if($lifeTime > 0 && (time() - self::$Driver->modificationTime($group, $idetnifier)) > $lifeTime) {
                
                self::$Driver->clear($group, $identifier);
                return false;
            }
            
            $data = self::$Driver->get($group, $identifier);
            
            if($data === false) return false;
            return ($unpack) ? unserialize($data) : $data;
        }
        catch (CacheException $e){
            
            if(self::$DebugMode) throw $e;
            else return false;
        }
    }
    
    
    /**
     * Существует кэш или нет
     * @param string $group Группа
     * @param string $identifier Индентификатор
     * @return boolean
     */
    public static function exists($group, $identifier) {
        
        if (!self::$Enable) {
            
            return false;
        }
        
        try {
            
            return self::$Driver->exists($group, $identifier);
        }
        catch (CacheException $e){
            
            if(self::$DebugMode) throw $e;
            else return false;
        }
    }
    
    
    /**
     * Удаление конкретного кэша
     * @param string $group
     * @param string $identifier
     * @return boolean
     */
    public static function clear($group, $identifier) {
        
        try {
            
            self::$Driver->clear($group, $identifier);
            return true;
        }
        catch (CacheException $e){
            
            if(self::$DebugMode) throw $e;
            else return false;
        }
    }
    
    
    /**
     * Очистка группы кэша
     * @param string $group Группа
     * @return boolean
     */
    public static function clearGroup($group) {
        
        try {
            
            self::$Driver->clearGroup($group);
            return true;
        }
        catch (CacheException $e){
            
            if(self::$DebugMode) throw $e;
            else return false;
        }
    }
    
    
    /**
     * Полная очистка кэша
     * @return boolean
     */
    public static function claerAll() {
        
        try {
            
            self::$Driver->clearAll();
            return true;
        }
        catch (CacheException $e){
            
            if(self::$DebugMode) throw $e;
            else return false;
        }
    }
    
    
    /**
     * Включение режима отладки
     * @return void
     */
    public static function debugModeOn(){
        
        self::$DebugMode = true;
    }
    
    
    /**
     * Выключение режима отладки
     * @return void
     */
    public static function debugModeOff(){
        
        self::$DebugMode = false;
    }
    
    
    /**
     * Включение кэширования
     * @return void
     */
    public static function enable() {
        
        self::$Enable = true;
    }
    
    
    /**
     * Выключение кэширования
     * @return void
     */
    public static function disable() {
        
        self::$Enable = false;
    }
}

class CacheException extends Exception {}